/**
 * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 */

package com.iwindplus.gateway.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.iwindplus.gateway.server.service.RouteService;
import jakarta.annotation.Resource;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 路由接口实现类.
 *
 * @author zengdegui
 * @since 2020/4/15
 */
@Component
@Slf4j
public class RouteServiceImpl implements RouteService, ApplicationEventPublisherAware {

    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private RouteDefinitionRepository routeDefinitionRepository;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void saveRoute(List<RouteDefinition> entities) {
        if (CollUtil.isEmpty(entities)) {
            return;
        }
        entities.stream().forEach(entity -> this.routeDefinitionRepository.save(Mono.just(entity)).subscribe());
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
    }

    @Override
    public void editRoute(List<RouteDefinition> entities) {
        this.delete(entities);
        this.saveRoute(entities);
    }

    @Override
    public void deleteRoute(List<RouteDefinition> entities) {
        this.delete(entities);
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
    }

    @Override
    public void refreshRoute(List<RouteDefinition> entities) {
        this.deleteAll();
        this.saveRoute(entities);
    }

    private void delete(List<RouteDefinition> entities) {
        if (CollUtil.isEmpty(entities)) {
            return;
        }
        entities.stream().forEach(entity -> this.routeDefinitionRepository.delete(Mono.just(entity.getId())).subscribe());
    }

    private void deleteAll() {
        Flux<RouteDefinition> routeDefinitions = this.routeDefinitionRepository.getRouteDefinitions();
        routeDefinitions.subscribe(routeDefinition -> this.routeDefinitionRepository.delete(Mono.just(routeDefinition.getId())).subscribe());
    }
}
